<?php
/**
 *
 * @author ninetyseven.
 * @date 2023-03-26 16:15
 */

namespace App\Lib\sms;

use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;
use AlibabaCloud\SDK\Dysmsapi\V20170525\Dysmsapi;
use AlibabaCloud\SDK\Dysmsapi\V20170525\Models\SendSmsRequest;
use AlibabaCloud\Tea\Exception\TeaError;
use AlibabaCloud\Tea\Utils\Utils\RuntimeOptions;
use App\Enum\SmsEnum;
use App\Models\SmsLogModel;
use Darabonba\OpenApi\Models\Config;
use Illuminate\Filesystem\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use function AlibabaCloud\Client\json;


class AliSms extends AbsService
{
    /**
     * 发送短信
     * @param string $phone
     * @param string $smsCode
     * @param string $way
     * @param string $areaCode
     * @return array|void
     * @author ninetyseven.
     * @date 2023-03-26 16:45
     */
    public static function sendSms(string $phone, string $smsCode, string $way = 'REGISTER', string $areaCode = "+86")
    {
        try {
            // 查看缓存中是否记录
            $redis = app("redis.connection");
            $isSmsCode = $redis->exists("USER:SMS:CODE:$phone");
            if ($isSmsCode) {
                throw new \Exception('验证码发送过于频繁，请1分钟后再试～');
            }

            $templateCode = env('ALISMS_TEMPLATE_CODE');

            $sms = new \Mrgoon\AliSms\AliSms();
            $result = $sms->sendSms($phone, $templateCode, ['code' => $smsCode]);
            Log::debug( 'send Sms result'.var_export($result,true));
            if ($result->Code == 'OK') {
                //存redis
                $redis->set("USER:SMS:CODE:LIMIT:$areaCode:$phone", $smsCode, "EX", 60); // 限制一分钟内发一条
                $redis->set("USER:SMS:CODE:$way:$areaCode:$phone", $smsCode, "EX", 300); // 失效时间为3分钟
                $redis->set("USER:SMS:CODE:COUNT:$way:$areaCode:$phone", 1, "EX", 300); // 记录验证码，验证次数
                return [true, null];
            } elseif ($result->Code == 'isv.BUSINESS_LIMIT_CONTROL') {
                Log::warning($result->Message);
                throw new \Exception($result->Message);
            } elseif ($result->Code == 'isv.SMS_TEST_NUMBER_LIMIT') {
                Log::warning($result->Message);
                throw new \Exception($result->Message);
            }
            return [false, '发送失败：'.$result->Message];
        } catch (ClientException | ServerException | \Exception $e) {
            Log::warning($e->getMessage());
            SmsLogModel::create([
                'type' => SmsEnum::SMS_TYPE_API,
                'mobile' => $phone,
                'code' => $smsCode,
                'status' => 2,
                'reason' => $e->getMessage(),
            ]);
            return [false, '网络异常 请稍后再试～'];
        }
    }

    /**
     * 又一个发送短信的方法
     * @param $phone
     * @param $params
     * @param $templateId
     * @return \$1|false|mixed|\SimpleXMLElement
     */
    public static function send($phone, $params, $templateId)
    {
        $sms = new \Mrgoon\AliSms\AliSms();
        return $sms->sendSms($phone, $templateId, $params);
    }

    public static function smsCheck($phone, $smsCode, $way = 'REGISTER', $areaCode = "+86")
    {
        $ck = "USER:SMS:CODE:COUNT:$way:$areaCode:$phone";
        $redis = app("redis.connection");
        // 验证码防爆破
        if ($redis->exists($ck)) {
            $limitCount = $redis->get($ck);
            if ($limitCount > 3) {
                return [false, '验证码错误次数太多，请重新获取'];
            }
        }
        $curSms = $redis->get("USER:SMS:CODE:$way:$areaCode:$phone");
        if ($curSms && $curSms != $smsCode) {
            $redis->incr($ck);
            return [false, '验证码错误'];
        }
        if (!$curSms) {
            return [false, '验证码过期'];
        }
        // 清除记录验证码，验证次数
        $redis->del($ck);
        return [true, null];
    }
}
